package com.block.common.exception;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.security.util.ApiUtil;
import com.block.common.service.LogFactory;
import com.block.common.util.LogFilterUtil;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.AppEncrypt;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Date;
import java.util.Set;

@RestControllerAdvice
public class ApiExceptionHandler {
    private static final Logger log = LogFactory.getErrorInfoLog();
    @Autowired
    NotifyExceptionService notifyExceptionService;

    @ExceptionHandler(com.block.common.exception.BizException.class)
    public String handleException(HttpServletRequest request, com.block.common.exception.BizException e) {
        //如果errorMsg为空 则表示为系统的message异常信息,不返回此异常信息.
        boolean isMsg = StrUtil.isEmpty(e.getErrorMsg());
        String uri = request.getRequestURI();
        String ip = (String) request.getAttribute("ip");
        JSONObject tranData = (JSONObject) request.getAttribute("tranData");
        String reqMsg=null;
        if(tranData!=null){
            reqMsg=tranData.toJSONString();
        }
        //出现系统异常.并非自定义异常
        if (isMsg) {
            if(StrUtil.isNotEmpty(reqMsg)){
                reqMsg= LogFilterUtil.filterLogs(reqMsg).toJSONString();
            }
            notifyExceptionService.notifyException("", uri, ip,reqMsg, e);
            log.error("系统异常", e);
        }
        ResponseVo responseVo = new ResponseVo(e.getErrorCode(), isMsg ? "System is busy " : e.getErrorMsg());
        AppEncrypt appEncrypt = (AppEncrypt) request.getAttribute("appEncrypt");
        return ApiUtil.dealReturnJson(responseVo, appEncrypt, new Date(),  uri);
    }

    @ExceptionHandler(com.block.common.exception.ApiException.class)
    public String handleException(HttpServletRequest request, com.block.common.exception.ApiException e) {
        //如果errorMsg为空 则表示为系统的message异常信息,不返回此异常信息.
        boolean isMsg = StrUtil.isEmpty(e.getErrorMsg());
        String uri = request.getRequestURI();
        String ip = (String) request.getAttribute("ip");
        JSONObject tranData = (JSONObject) request.getAttribute("tranData");
        String reqMsg=null;
        if(tranData!=null){
            reqMsg=tranData.toJSONString();
        }
        //出现系统异常.并非自定义异常
        if (isMsg) {
            if(StrUtil.isNotEmpty(reqMsg)){
                reqMsg= LogFilterUtil.filterLogs(reqMsg).toJSONString();
            }
            notifyExceptionService.notifyException("", uri, ip, reqMsg, e);
            log.error("系统异常", e);
        }
        ResponseVo responseVo = new ResponseVo(e.getErrorCode(), isMsg ? "System is busy " : e.getErrorMsg());

        AppEncrypt appEncrypt = (AppEncrypt) request.getAttribute("appEncrypt");
        return ApiUtil.dealReturnJson(responseVo, appEncrypt,  new Date(), uri);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public String handleException(HttpServletRequest request, ConstraintViolationException e) {

        Set<ConstraintViolation<?>> s = e.getConstraintViolations();

        ResponseVo responseVo = null;
        StringBuffer smessage = new StringBuffer();
        for (ConstraintViolation<?> c : s) {
            String message = c.getMessage();
            smessage.append(message).append("|");
        }
        responseVo = new ResponseVo(AppRspCodeConstant.PARAM_ERROR, smessage.toString());
        AppEncrypt appEncrypt = (AppEncrypt) request.getAttribute("appEncrypt");
        String uri = request.getRequestURI();
        String lang = (String) request.getAttribute("lang");
        return ApiUtil.dealReturnJson(responseVo, appEncrypt, new Date(), uri);
    }

    /**
     * 参数校验错误
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public String handleException(HttpServletRequest request, BindException e) {
        BindingResult bindingResult = e.getBindingResult();


        ResponseVo responseVo = null;
        if (bindingResult.hasErrors() && bindingResult.hasFieldErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            String errorMsg = fieldError.getDefaultMessage();
            String fileName = fieldError.getField();
            responseVo = new ResponseVo(AppRspCodeConstant.PARAM_ERROR, fileName + "," + errorMsg);
        } else {

            responseVo = new ResponseVo(AppRspCodeConstant.PARAM_ERROR, e.getMessage());
        }


        AppEncrypt appEncrypt = (AppEncrypt) request.getAttribute("appEncrypt");
        String uri = request.getRequestURI();
        return ApiUtil.dealReturnJson(responseVo, appEncrypt,  new Date(), uri);
    }

    @ExceptionHandler(Exception.class)
    public String handleException(HttpServletRequest request, Exception e) {

        ResponseVo responseVo = new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "SYSTEM ERROR APIEXEC");
        String uri = request.getRequestURI();
        AppEncrypt appEncrypt = (AppEncrypt) request.getAttribute("appEncrypt");
        String ip = (String) request.getAttribute("ip");
        if (appEncrypt != null) {
            JSONObject tranData = (JSONObject) request.getAttribute("tranData");

            notifyExceptionService.notifyException("", uri, ip, tranData.toJSONString(), e);
            return ApiUtil.dealReturnJson(responseVo, appEncrypt,  new Date(), uri);
        }
        notifyExceptionService.notifyException("", uri, ip, "", e);
        return JSONObject.toJSONString(responseVo);

    }

}
